<?PHP

namespace Lib;

use Lib\db\MongoDb;

/**
 * Modell基类
 * @package SDF\Core
 */
class Model extends MongoDb {

    /**
     * 与模型关联的集合。
     *
     * @var string
     */
    protected $collectionName = '';

    /**
     * 数据模型专属的数据库连接
     *
     * @var string
     */
    protected $connection = '';

    /**
     * 分页参数名
     * @var string
     */
    protected $pageNmae = 'page';
    /**
     * 分页参数列表（通过appends方法添加）
     * @var array
     */
    protected $appends = [];

    /**
     * 构造函数
     * Model constructor.
     */
    public function __construct($collectionName = null,$connection = null) {
        if(empty($collectionName)){
            $collectionName = $this->collectionName;
        }
        if(empty($connection)){
            $connection = $this->connection;
        }
        parent::__construct($collectionName, $connection);
    }

    /**
     * 添加分页参数
     * @param $appends
     * @return $this
     */
    public function appends($appends){
        $this->appends = array_merge( $this->appends,$appends);
        return $this;
    }
    /**
     * @var array
     */
    protected $filter = [];

    /**
     * 筛选条件
     * @return array
     */
    public function getFilter(): array
    {
        return $this->filter;
    }

    /**
     * 设置筛选条件
     * @param array $filter
     * @return Model
     */
    public function setFilter(array $filter)
    {
        $this->filter = $filter;
        return $this;
    }

    /**
     * 查询结果需要的属性
     * @return array
     */
    public function getProjection(): array
    {
        return $this->projection;
    }

    /**
     * 设置查询结果需要的属性
     * @param array $projection
     * @return Model
     */
    public function setProjection(array $projection)
    {
        $this->projection = $projection;
        return $this;
    }

    /**
     * 获取结果集限制数量
     * @return int
     */
    public function getLimit(): int
    {
        return $this->limit;
    }

    /**
     * 设置结果集限制数量
     * @param int $limit
     * @return Model
     */
    public function setLimit(int $limit)
    {
        $this->limit = $limit;
        return $this;
    }

    /**
     * @return int
     */
    public function getSkip(): int
    {
        return $this->skip;
    }

    /**
     * @param int $skip
     * @return Model
     */
    public function setSkip(int $skip)
    {
        $this->skip = $skip;
        return $this;
    }

    /**
     * @return array
     */
    public function getSort(): array
    {
        return $this->sort;
    }

    /**
     * @param array $sort
     * @return Model
     */
    public function setSort(array $sort)
    {
        $this->sort = $sort;
        return $this;
    }

    /**
     * @var array
     */
    protected $projection = [];//结果集字段筛选
    /**
     * @var int
     */
    protected $limit = 0;//每页显示多少条，默认0，显示所有
    protected $skip = 0;//查询时，跳过多少条数据
    /**
     * @var array
     */
    protected $sort = [];

    /**
     * 分页结果参数
     * @var array
     */
    protected $paginateData = [
        'status'=>200,
        "total" => 50,//总数
        "per_page" => 30,//每页显示数量
        "current_page" => 1,//当前第几页
        "last_page" => 0,//一共多少页
        "first_page_url" => "http://laravel.app?page=1",//首页
        "last_page_url" => "http://laravel.app?page=4",//最后一页
        "next_page_url" => "http://laravel.app?page=2",//下一页
        "prev_page_url" => null,//上一页
        "path" => "",//域名
        "from" => 1,//开始条数
        "to" => 15,//结束条数
        "data" => [
            //结果集
        ]
    ];

    /**
     * xxx
     * @param $url
     */
    public function setPaginatePath($url){
        $this->paginateData['path'] = $url;
    }
    /**
     * 分页查询
     * @param int $per_page
     * @return array
     * @throws \Exception
     */
    public function paginate(int $per_page = 30){
        if(empty($this->paginateData['path'] )){
            $parse = parse_url($_SERVER['REQUEST_URI']);
            $this->paginateData['path'] = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].$parse['path'];
        }

        if ($per_page <= 0) throw new \Exception('$per_page not <= 0 ');
        $current_page = empty($_REQUEST[$this->pageNmae])?1:intval($_REQUEST[$this->pageNmae]);//获取请求的页数，默认为1
        $this->paginateData['current_page'] = $current_page < 1 ? 1 : $current_page;//当前第几页
        $this->paginateData['per_page'] = $per_page;//每页条数
        $this->paginateData['from'] = $per_page * ($current_page-1);//开始第几条
        $this->paginateData['to'] = $this->paginateData['from'] + $per_page;//到多少条结束

        $this->paginateData['total'] = self::count($this->filter);//总数
        $this->paginateData['last_page'] = $this->paginateData['total']>0 ? ceil($this->paginateData['total']/$this->paginateData['per_page']):0;//一共多少页

        //$this->paginateData['path'] = '/';//todo 初始化分类页路径
        $this->appends[$this->pageNmae] = 1;
        $this->paginateData['first_page_url'] = $this->paginateData['path'] . '?'.http_build_query($this->appends);
        $this->appends[$this->pageNmae] = $this->paginateData['last_page'];
        if ($this->appends[$this->pageNmae] <= $this->paginateData['last_page'] )$this->paginateData['last_page_url'] = $this->paginateData['path'] . '?'.http_build_query($this->appends);
        $this->appends[$this->pageNmae] = $this->paginateData['current_page'] + 1;
        if ($this->appends[$this->pageNmae] <= $this->paginateData['last_page'] )$this->paginateData['next_page_url'] = $this->paginateData['path'] . '?'.http_build_query($this->appends);
        $this->appends[$this->pageNmae] = $this->paginateData['current_page'] - 1;
        if ($this->appends[$this->pageNmae] > 0 )$this->paginateData['prev_page_url'] = $this->paginateData['path'] . '?'.http_build_query($this->appends);

        $this->setSkip($this->paginateData['from']);
        $this->setLimit($per_page);

        $this->paginateData['data'] = $this->get();
        return $this->paginateData;
    }

    /**
     * 简单分页
       如果你只需要在分页视图中显示简单的「下一页」和「上一页」的链接，即不需要显示每个页码的链接，更推荐使用 simplePaginate 方法来执行更高效的查询，这对于大型数据集非常有用：
     */
    public function simplePaginate(){
        $cursor = $this->find($this->filter,$this->projection,$this->limit,$this->skip,$this->sort);
        $cursor->setTypeMap(['root' => 'array']);
        $this->paginateData['data'] = $cursor->toArray();
        return $this->paginateData;
    }

    /**
     * 析构函数
     */
    public function __destruct()
    {
        $this->paginateData['data'] = [];
    }

    /**
     *  获取数据
     */
    public function get(){
        $cursor = $this->find($this->filter,$this->projection,$this->limit,$this->skip,$this->sort);
        $cursor->setTypeMap(['root' => 'array','document'=>'array']);
        return $cursor->toArray();

    }


}